package hotciv.view.stubs;

import java.util.ArrayList;
import java.util.List;

import hotciv.framework.Game;
import hotciv.framework.GameObserver;
import hotciv.framework.Position;
import hotciv.framework.Tile;
import hotciv.framework.Unit;
import hotciv.standard.GameConstants;
import hotciv.standard.StandardPlayer;
import hotciv.standard.StandardTile;
import hotciv.standard.StandardUnit;

/** Abstract base class for game test stubs.*/
public abstract class AbstractGame implements Game {

  private List<Tile> world;
  protected Position pos_archer;
  protected Position pos_legion;
  protected Unit archer;
  protected Unit legion;
  protected GameObserver to = null;

  public AbstractGame() {  
    defineWorld(1);
    pos_archer = new Position(3,8);
    pos_legion = new Position( 4, 4 );

    archer = new StandardUnit( GameConstants.ARCHER, StandardPlayer.RED );
    legion = new StandardUnit( GameConstants.LEGION, StandardPlayer.BLUE ) {
      public int getMoveCount() { return 0; }
    };  
  }

  public Tile getTile(Position p) {
    return world.get(p.getRow()*WORLDSIZE+p.getColumn());
  }

  public Unit getUnitAt(Position p) {
    if ( p.equals(pos_archer) ) {
      return archer;
    }
    if ( p.equals(pos_legion) ) {
      return legion;
    }
    
    return null;
  }

  @Override
  public void changeProductionInCityAt(Position p, String unitType) {
    System.out.println( "City at "+p+ " change production to "+unitType);
  }

  @Override
  public void changeWorkForceFocusInCityAt(Position p, String balance) {
    System.out.println( "City at "+p+" change workforce focus to "+ balance);
  }

  /** move units - all moves are valid, except
   * 1) moving to (0,0)
   * 2) moving to the location of another unit
   */
  @Override
  public boolean moveUnit(Position from, Position to) {
    // find out if it is a battle
    System.out.println( "Moving from "+ from + " to "+ to);
  
    if ( to.equals( new Position(0,0) ) ) { return false; }
    if ( from.equals( pos_archer ) && ! to.equals( pos_legion )) {
      pos_archer = to;
      _changedAt(from);
      _changedAt(to);
      return true;
    }
    if ( from.equals( pos_legion ) && ! to.equals( pos_archer )) {
      pos_legion = to;
      _changedAt(from);
      _changedAt(to);
      return true;
    }
    return false;
  }

  protected void _changedAt(Position p) {
    if ( to != null ) {
      to.tileChanged(p);
    }
  }
  
  public void addGameObserver(GameObserver observer) {
    to = observer;
  }

  /** define the world.
   * @param worldType 1 gives one layout while all other
   * values provide a second world layout.
   */
  protected void defineWorld(int worldType) {
    world = new ArrayList<Tile>();
    String[] layout;
    if ( worldType == 1 ) {
      layout = new String[] {
          "...ooMooooo.....",
          "..ohhoooofffoo..",
          ".oooooMooo...oo.",
          ".ooMMMoooo..oooo",
          "...ofooohhoooo..",
          ".ofoofooooohhoo.",
          "...ooo..........",
          ".ooooo.ooohooM..",
          ".ooooo.oohooof..",
          "offfoooo.offoooo",
          "oooooooo...ooooo",
          ".ooMMMoooo......",
          "..ooooooffoooo..",
          "....ooooooooo...",
          "..ooohhoo.......",
          ".....ooooooooo..",
         };
    } else {
      layout = new String[] {
          "...ooo..........",
          ".ooooo.ooohooM..",
          ".ooooo.oohooof..",
          "offfoooo.offoooo",
          "oooooooo...ooooo",
          ".ooMMMoooo......",
          ".....ooooooooo..",
          "...ooMooooo.....",
          "..ohhoooofffoo..",
          "...ofooohhoooo..",
          ".oooooMooo...oo.",
          ".ooMMMoooo..oooo",
          ".ofoofooooohhoo.",
          "..ooooooffoooo..",
          "....ooooooooo...",
          "..ooohhoo.......",
         };      
    }
    String line;
    for ( int r = 0; r < Game.WORLDSIZE; r++ ) {
      line = layout[r];
      for ( int c = 0; c < Game.WORLDSIZE; c++ ) {
        char tileChar = line.charAt(c);
        String type = "error";
        if ( tileChar == '.' ) { type = GameConstants.OCEANS; }
        if ( tileChar == 'o' ) { type = GameConstants.PLAINS; }
        if ( tileChar == 'M' ) { type = GameConstants.MOUNTAINS; }
        if ( tileChar == 'f' ) { type = GameConstants.FOREST; }
        if ( tileChar == 'h' ) { type = GameConstants.HILLS; }
        world.add( new StandardTile(type, r, c ));
      }
    }
  }

}